import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Any, Like, Not, Repository, UpdateResult } from 'typeorm';
import { SortType } from '../../common/constants/common.constant';
import { AreaEntity } from '../entities/area.entity';

@Injectable()
export class AreaService {
  constructor(@InjectRepository(AreaEntity) private readonly areaRepository: Repository<AreaEntity>) {}

  /**
   * 创建区域
   * @param name 区域名称
   * @param description 区域描述
   */
  async create(name: string, description?: string): Promise<AreaEntity> {
    const areaEntity = new AreaEntity();
    areaEntity.name = name;
    areaEntity.description = description;

    return this.areaRepository.save(areaEntity);
  }

  /**
   * 通过Uuid删除区域（软删除）
   * @param uuid 区域Uuid
   */
  async deleteOneByUuid(uuid: string): Promise<UpdateResult> {
    return this.areaRepository.update({ uuid: uuid }, { deleted: true });
  }

  /**
   * 更新区域信息
   * @param uuid 区域Uuid
   * @param name 区域名称
   * @param description 区域描述
   */
  async update(uuid: string, name: string, description?: string): Promise<UpdateResult> {
    return this.areaRepository.update(uuid, { name, description });
  }

  /**
   * 获取区域信息
   * @param uuid 区域Uuid
   */
  async findOneByUuid(uuid: string): Promise<AreaEntity> {
    return this.areaRepository.findOne({ uuid: uuid, deleted: false });
  }

  /**
   * 通过区域名称获取区域信息
   * @param name 区域名称
   */
  async findOneByName(name: string): Promise<AreaEntity> {
    return this.areaRepository.findOne({ name: name, deleted: false });
  }

  /**
   * 检查重名
   * @param name 名称
   * @param uuid 编号
   */
  async checkDuplicateByName(name: string, uuid?: string): Promise<number> {
    if (uuid) return this.areaRepository.count({ uuid: Not(uuid), name: name, deleted: false });
    else return this.areaRepository.count({ name: name, deleted: false });
  }

  /**
   * 通过Uuid列表获取区域信息
   * @param areaUuidList 区域Uuid列表
   */
  async findByUuids(areaUuidList: string[]): Promise<AreaEntity[]> {
    return this.areaRepository.createQueryBuilder('areas').where('areas.uuid = ANY(:areaUuidList) AND devices.deleted = false', { areaUuidList }).orderBy('areas.createdAt', 'DESC').getMany();
  }

  /**
   * 通过名称获取指定数量的区域信息
   * @param take 数量
   * @param name 名称
   * @param organizationIdList 组织编号列表
   */
  async findForQuery(take: number, name?: string, organizationIdList?: number[]): Promise<AreaEntity[]> {
    return this.areaRepository.find({
      where: Object.assign({ deleted: false }, name ? { name: Like(`%${name}%`) } : {}, organizationIdList ? { creatorJobId: Any(organizationIdList) } : {}),
      order: { ['name']: 'ASC' },
      take: take
    });
  }

  /**
   * 分页获取区域信息
   * @param pageIndex 页码
   * @param pageSize 页容量
   * @param name 名称模糊查询依据
   * @param organizationIdList 用户组织id列表
   */
  async findAndPaging(pageIndex: number, pageSize: number, sortType: SortType, name?: string, organizationIdList?: number[]): Promise<[AreaEntity[], number]> {
    const queryConditionList = ['areas.deleted = false'];
    if (name) queryConditionList.push('areas.name LIKE :name');
    if (organizationIdList) queryConditionList.push('areas.creator_job_id = ANY(:organizationIdList)');

    const queryCondition = queryConditionList.join(' AND ');
    const orderBy = 'areas.createdAt';

    return this.areaRepository
      .createQueryBuilder('areas')
      .where(queryCondition, {
        name: `%${name}%`,
        organizationIdList: organizationIdList
      })
      .orderBy(orderBy, sortType)
      .skip(pageIndex * pageSize)
      .take(pageSize)
      .getManyAndCount();
  }
}
